#include <cmath>
#include "structs.h"

bool point::operator ==(const point& p) const
{
    return (x == p.x) && (y == p.y);
}

bool point::operator !=(const point& p) const
{
    return (!(*this == p));
}

bool point::operator <(const point& a) const
{
    return ((x < a.x) || ((x == a.x) && (y < a.y)));
}

bool point::operator <=(const point& a) const
{
    return ((*this < a) || (*this == a));
}

bool segment::operator ==(const segment& p) const
{
    return (first == p.first) && (second == p.second);
}

segment::segment(const point& a, const point& b)
{
    if (a.x > b.x)
	{
        second = a;
		first = b;
	}
    else
	{
        first = a;
		second = b;
	}
    if (second.x == first.x)
        slope = std::numeric_limits<double>::infinity();
    else
	{
        slope = (second.y - first.y) / (second.x - first.x);
        y_intercept = first.y - slope * first.x;
    }
}

bool segment::intersects_with_x(int x) const
{
    return (x >= first.x) && (x <= second.x);
}

template <class T>
void segment::y_at(int x, T& result) const
{
    if (slope = std::numeric_limits<double>::infinity())
        result = std::numeric_limits<double>::infinity();
    else
    {
        T a_x(this->first.x), b_x(this->second.x), a_y(this->first.y), b_y(this->second.y);
        T x0(x);

        result = (a_y * (b_x - x0) + b_y * (x0 - a_x)) / (b_x - a_x);
    }
}